import React, { useEffect, useState } from 'react'
import { Anchor } from 'antd'
import style from './index.module.scss'

type Title = {
    key: string;
    href: string;
    title: string;
    children?: Title[]; // 存放下一级标签，例如：如果当前是h1，下一级h2就存放到children
    nodeName: string;
}

// 格式化markdown标题的dom节点数组
const formatNavItem = (rootElement: NodeListOf<HTMLElement>) => {
    // 将NodeList转换为数组，并提取出需要的属性
    let rootElementARR = Array.prototype.slice
        .call(rootElement)
        .map((item, index) => {
            let title = {
                href: "#" + index,
                key: "" + index,
                title: rootElement[index].innerText,
                nodeName: item.nodeName,
                children: [],
            }
            return title
        }) as Title[]

    /**
     * (双重循环，从后往前，逐渐将子节点存入父节点children属性)
     * 1. 从后往前，将子标题直接存入前一个父级标题的children[]中
     * 2. 如果前一个标题与当前标题(或标题数组)无直系关系，则直接将当前标题(或标题数组解构后)放入list数组
     * 3. 循环多次，直到result数组长度无变化，结束循环
     */
    let result = rootElementARR
    let preLength = 0
    let newLength = result.length
    let num = 0
    while (preLength !== newLength) {
        num++
        preLength = result.length // 获取处理前result数组长度
        let list: Title[] = [] // list数组用于存储本次for循环结果
        let childList: Title[] = [] // childList存储遍历到的兄弟标题，用于找到父标题时赋值给父标题的children属性
        for (let index = result.length - 1; index >= 0; index--) {
            if (
                // 当前节点与上一个节点是兄弟节点，将该节点存入childList数组
                result[index - 1] &&
                result[index - 1].nodeName.charAt(1) ===
                result[index].nodeName.charAt(1)
            ) {
                childList.unshift(result[index])
            } else if (
                // 当前节点是上一个节点的子节点，则将该节点存入childList数组，将childList数组赋值给上一节点的children属性，childList数组清空
                result[index - 1] &&
                result[index - 1].nodeName.charAt(1) <
                result[index].nodeName.charAt(1)
            ) {
                childList.unshift(result[index])
                result[index - 1].children = [
                    ...(result[index - 1].children as []),
                    ...childList,
                ]
                childList = []
            } else {
                // 当前节点与上一个节点无直系关系，或当前节点下标为0的情况
                childList.unshift(result[index])
                if (childList.length > 0) {
                    list.unshift(...childList)
                } else {
                    list.unshift(result[index])
                }
                childList = []
            }
        }
        result = list
        newLength = result.length // 获取处理后result数组长度
    }
    return result
}

const MarkdownNav: React.FC<{ content: string }> = ({ content }) => {

    let [titles, setTitles] = useState<Title[]>([])

    useEffect(() => {
        setTitles(addAnchor())
    }, [content])

    // 添加锚链接
    const addAnchor = (): Title[] => {
        // const ele: HTMLElement = document.querySelector('.markdown-body') as HTMLElement
        // let eid = 0
        // let titles: Title[] = []
        // let titleNode = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6']
        // for (const e of ele!.childNodes) {
        //     if (titleNode.includes(e.nodeName)) {
        //         // id要和下面title.href的"#"后的内容相对应
        //         (e as HTMLElement).setAttribute('id', eid.toString())
        //         let title = {
        //             href: "#" + eid,
        //             key: "#" + eid.toString(),
        //             title: (e as HTMLElement).innerText,
        //             nodeName: e.nodeName,
        //             children: []
        //         }
        //         titles.push(title)
        //         eid++
        //     }
        // }
        // return titles

        // 获取markdown标题的dom节点
        const rootElement: NodeListOf<HTMLElement> = (document.querySelector('.markdown-body') as HTMLElement).querySelectorAll(
            "h1, h2, h3, h4, h5, h6"
        )
        // 向标题中注入id，用于锚点跳转
        rootElement.forEach((navItem, index) => {
            navItem.setAttribute("id", index.toString())
        })
        // 格式化标题数组，用于antd锚点组件自动生成锚点
        let titles = formatNavItem(rootElement)
        
        return titles
    }

    // 点击锚链接回调
    const handleClickAnchor = (e: React.MouseEvent<HTMLElement, MouseEvent>, link: {
        title: React.ReactNode;
        href: string;
    }) => {
        e.preventDefault()
        if (link.href) {
            let element = document.getElementById(link.href)
            // 对应id的锚点存在，就跳滚动到锚点顶部
            element && element.scrollIntoView({ block: "start", behavior: "smooth" })
        }
    }

    // 自定义高亮锚点
    const getCurrentAnchor = (activeLink: string = '#0'): string => {
        if (!activeLink) activeLink = '#0'
        return activeLink
    }

    if (titles.length > 0) {
        return <Anchor
            className={`${style.markdownNavContent} scrollbar-hidden`}
            affix={false}
            items={titles}
            getCurrentAnchor={getCurrentAnchor}
            onClick={handleClickAnchor}
            getContainer={() => document.querySelector('.markdown-body') as HTMLElement}
        />
    }
}

export default MarkdownNav